<template>
  <div class="container">
    <!-- 动态加载左侧分类菜单 -->
    <!-- el-menu 是 Element Plus 的导航菜单组件 -->
    <!-- :default-active，默认选中的菜单项 -->
    <!-- @select，菜单选择事件 -->
    <el-menu
        class="side-menu"
        :default-active="activeCategory"
        @select="activeCategory = Number($event)"
    >
      <!-- 循环生成菜单项 -->
      <template v-for="item in categories" :key="item.id">
        <!-- 如果有子菜单，显示为折叠菜单 -->
        <el-sub-menu v-if="item.children?.length" :index="item.id">
          <!-- 父级菜单标题 -->
          <template #title>{{ item.label }}</template>
          <!-- 循环生成子菜单项 -->
          <el-menu-item v-for="child in item.children" :key="child.id" :index="child.id">
            {{ child.label }}
          </el-menu-item>
        </el-sub-menu>
        <!-- 没有子菜单的直接显示为菜单项 -->
        <el-menu-item v-else :index="item.id">{{ item.label }}</el-menu-item>
      </template>
    </el-menu>

    <!-- 右侧内容区域 -->
    <div class="content-area" style="text-align: left">
      <!-- 工具栏按钮 -->
      <div class="toolbar">
        <el-button type="primary" v-if="props.flag" @click="checkConfirm">使用选中图片</el-button>
        <!-- 图片上传组件 -->
        <!-- :before-upload，上传前的校验 -->
        <!-- :on-success，上传成功处理 -->
        <!-- :data，文件上传时携带的参数，分类ID -->
        <el-upload
            action="http://localhost:8081/upload"
            :headers="uploadHeaders"
            :data="{ categoryId: activeCategory }"
            :before-upload="validateImage"
            :on-success="handleUpload"
        >
          <el-button type="primary">上传图片</el-button>
        </el-upload>
        <!-- 删除按钮，删除数据库数据以及磁盘文件 -->
        <el-button type="danger" @click="deleteSelected">删除图片</el-button>
        <!-- 分类搜索下拉框 -->
        <el-dropdown trigger="click" class="search-dropdown">
          <!-- 显示当前选中分类的输入框 -->
          <!-- readonly，只读模式，点击后展开下拉-->
          <!-- @click，点击时清空搜索关键词 -->
          <el-input
              v-model="selectedLabel"
              placeholder="输入分类名称搜索"
              readonly
              @click="searchKeyword = ''"
          >
          </el-input>
          <!-- 下拉内容 -->
          <template #dropdown>
            <div class="dropdown-content">
              <el-input v-model="searchKeyword" placeholder="搜索分类" clearable/>
              <!-- 树形分类列表 -->
              <!-- :data，过滤后的树数据 -->
              <!-- :filter-node-method，节点过滤方法 -->
              <!-- @node-click，节点点击事件 -->
              <el-tree
                  :data="filteredTreeData"
                  node-key="id"
                  :props="{ children: 'children', label: 'label' }"
                  :filter-node-method="filterNode"
                  @node-click="handleNodeClick"
              />
            </div>
          </template>
        </el-dropdown>
        <el-button @click="moveImages" :disabled="!selectedCategory">确认移动</el-button>
        <el-button @click="toggleAllSelection">
          {{ isAllSelected ? '全不选' : '全选' }}
        </el-button>
      </div>
      <!-- 图片展示 -->
      <el-row :gutter="12">
        <!-- 循环渲染图片卡片 -->
        <el-col v-for="(img, index) in images" :key="index" :xs="12" :sm="8" :md="6" :lg="4">
          <!-- :class，选中状态样式 -->
          <!-- @click，点击选择事件 -->
          <div
              class="image-card"
              :class="{ selected: img.selected }"
              @click="handleSelect($event, img)"
          >
            <!-- 选中时显示的图标 -->
            <el-icon v-if="img.selected" class="selected-icon"><Select/></el-icon>
            <!-- 图片显示 -->
            <el-image :src="imageBase+img.fileName" fit="cover" style="height: 260px"/>
            <!-- 图片名称 -->
            <div class="image-name">{{ img.fileName }}</div>
          </div>
        </el-col>
      </el-row>
      <!-- 分页组件 -->
      <div class="pagination">
        <el-pagination
            background
            :total="100"
            :page-size="20"
            layout="prev, pager, next"
            @current-change="page => console.log('当前页:', page)"
        />
      </div>
    </div>
  </div>
</template>

<script setup>
import {ref, computed, getCurrentInstance, onMounted, defineProps, defineEmits, watch} from 'vue';
import {Select} from '@element-plus/icons-vue';
import {ElMessage} from 'element-plus';
// 引入Axios
const axios = getCurrentInstance().appContext.config.globalProperties.$axios;
// 分类数据，左侧菜单栏以及下拉框数据
const categories = ref([
  {label: '全部图片', id: 0},
  {
    label: '商品图片', id: 1, children: [
      {label: '分类图片', id: 2}, {label: '商品图片', id: 3}, {label: '其他图片', id: 4}
    ]
  },
  {
    label: '其他图片', id: 5, children: [
      {label: '用户头像', id: 6}, {label: '用户照片', id: 7}
    ]
  },
  {label: '风景图片', id: 8}
]);
// 图片集合
const images = ref([{
  url: "",
  name: "",
  selected: false, // 初始值，表示是否选中
  categoryId: ""
}]);
// 后台图片地址
const imageBase = ref('http://localhost:8081/uploads/')
// 当前选中的分类ID
const activeCategory = ref(0);
// 移动目标分类ID
const selectedCategory = ref(null);
// 搜索关键词
const searchKeyword = ref('');
// 下拉框显示文本
const selectedLabel = ref('图片移动至');
// 最后选中的图片索引（用于Shift多选）
const lastSelectedIndex = ref(-1);
// 选中图片ID及名称
const imageIds = ref([])
const imageNames = ref([])
// 选中图片对象
const selectedImage = ref({})
// 父子页面传参
const emit = defineEmits(['selectImage']) // 声明自定义事件
const checkConfirm = () => {
  emit('selectImage', selectedImage.value) // 注意.value
}
const props = defineProps({
  flag: {
    type: Number,
    default: 0
  }
})

// 监听器：当activeCategory变化时重新加载数据，实现点击左侧菜单切换图片数据
watch(activeCategory, () => {
  filteredImages();
});

// 根据当前选中的分类过滤图片
const filteredImages = async () => {
  // 使用分类ID去后台获取数据
  let res = await axios.get(`/getMaterial/${activeCategory.value}?page=1&size=50`);
  images.value = res.data.data.records;
};

// 文件上传成功处理事件
const handleUpload = (res, file) => {
  if (res.code === "1") {
    images.value.unshift({url: res.data.url, name: file.name, selected: false});
    ElMessage.success('上传成功');
  } else {
    ElMessage.error(res.message || '上传失败');
  }
};

// 移动图片，更改图片分类信息
const moveImages = () => {
  if (!selectedCategory.value) return ElMessage.warning('请选择目标分类');
  const selected = images.value.filter(img => img.selected);
  if (!selected.length) return ElMessage.warning('请选择要移动的图片');
  // 调用后台API接口
  let res = axios.put('/updClassify', {
    ids: selected.map(img => img.id),
    categoryId: selectedCategory.value
  });
  console.log(res);
  ElMessage.success(`已移动${selected.length}张图片`);
  images.value.forEach(img => img.selected = false);
  selectedCategory.value = null;
};

// 点击图片时的选择逻辑
const handleSelect = (e, img) => {
  // Shift键多选
  if (e.shiftKey && lastSelectedIndex.value !== -1) {
    const [start, end] = [lastSelectedIndex.value, img.id].sort((a, b) => a - b);
    images.value.forEach((v, i) => v.selected = i >= start && i <= end);
  } else if (e.ctrlKey) {
    // Ctrl键单选切换
    img.selected = !img.selected;
  } else {
    // 普通单选
    images.value.forEach(v => v.selected = false);
    img.selected = true;
  }
  // 更新imageIds和imageNames
  if (img.selected) {
    selectedImage.value = img
    imageIds.value.push(img.id)
    imageNames.value.push(img.fileName)
  } else {
    imageIds.value = imageIds.value.filter(id => id !== img.id)
    imageNames.value = imageNames.value.filter(name => name !== img.fileName)
  }
};

// 是否全部选中
const isAllSelected = computed(() =>
    images.value.length > 0 && images.value.every(img => img.selected)
);

// 过滤后的分类树数据（根据搜索关键词）
const filteredTreeData = computed(() =>
    filterTreeData(searchKeyword.value ? categories.value : categories.value)
);

/**
 * 递归过滤分类树数据
 * @param {Array} nodes - 当前层级的节点数组
 * @returns 过滤后的节点数组
 */
const filterTreeData = nodes => nodes.filter(node => {
  // 匹配当前节点的标签
  const match = node.label.toLowerCase().includes(searchKeyword.value.toLowerCase());
  // 处理子节点
  if (node.children) {
    // 递归过滤子节点
    const children = filterTreeData(node.children);
    // 更新子节点
    node.children = children
    // 当前节点或子节点有匹配则保留
    return match || children.length > 0;
  }
  return match;
});

// 树节点过滤方法（Element Tree 内置方法）
const filterNode = (value, data) => {
  return data.label.toLowerCase().includes(value.toLowerCase());
};

// 点击树节点时触发
const handleNodeClick = (node) => {
  selectedCategory.value = node.id;
  selectedLabel.value = node.label;
};

// 全选/全不选点击事件
const toggleAllSelection = () => {
  const select = !isAllSelected.value;
  images.value.forEach(img => img.selected = select);
};

// 删除选中图片
const deleteSelected = async () => {
  images.value = images.value.filter(img => !img.selected);
  let res = await axios.post('/delMaterial', {
    ids: imageIds.value,
    fileName: imageNames.value
  });
  if (res.data.code === "1") {
    ElMessage.success('删除成功');
  } else {
    ElMessage.error(res.message || '删除失败');
  }
};

// 验证图片规格
const validateImage = (file) => {
  const isValidType = ['image/jpeg', 'image/png', 'image/gif'].includes(file.type);
  const isValidSize = file.size / 1024 / 1024 < 2;
  if (!isValidType) ElMessage.error('仅支持JPEG/PNG/GIF格式');
  if (!isValidSize) ElMessage.error('文件需小于2MB');
  return isValidType && isValidSize;
};

// 文件上传头部添加token
const uploadHeaders = ref({
  Authorization: 'Bearer ' + localStorage.getItem('token')
});

onMounted(filteredImages);
</script>

<style scoped>
.container {
  display: flex;
  height: 100vh;
}

.side-menu {
  width: 240px;
  border-right: 1px solid #eee;
}

.content-area {
  flex: 1;
  padding: 20px;
  overflow: auto;
}

.toolbar {
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  gap: 10px; /* 使用gap统一间距 */
  flex-wrap: wrap; /* 允许换行 */
}

/* 调整上传组件为行内布局 */
.toolbar :deep(.el-upload) {
  margin-top: 10px;
  display: inline-block;
}

.search-dropdown {
  display: inline-flex;
  margin-left: 0;
}

/* 调整树形下拉框宽度 */
.dropdown-content {
  width: 260px;
  padding: 8px;
}

.image-card {
  position: relative;
  cursor: pointer;
  transition: all 0.2s;

  &.selected {
    border: 2px solid #409EFF;
    box-shadow: 0 2px 12px rgba(64, 158, 255, 0.3);
  }
}

.selected-icon {
  position: absolute;
  top: 5px;
  right: 5px;
  color: #409EFF;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 50%;
}

.image-name {
  padding: 8px;
  font-size: 12px;
  text-align: center;
  background: #fff;
}

.pagination {
  margin-top: 20px;
  justify-content: center;
}

/* 调整输入框样式 */
:deep(.el-input__inner) {
  cursor: pointer;
  background-color: var(--el-button-bg-color);
  border-color: var(--el-button-border-color);
}

:deep(.el-input__inner):hover {
  border-color: var(--el-button-hover-border-color);
}
</style>
